/**
 * 
 * 要求最大并发数 maxNum
 * 每当有一个请求返回，就留下一个空位，可以增加新的请求
 * 所有请求完成后，结果按照 urls 里面的顺序依次打出（发送请求的函数可以直接使用fetch即可）
 * 
 * 并发请求
 * @param {Array} urls 请求地址
 * @param {Number} limit 最大并发数
 */

const urls = [];
for (let i = 1; i <= 20; i++) {
    urls.push(`http://localhost:5001/test/${i}`);
}
concurrencyRequest(urls, 5, 2400).then(res => {
    console.log(res)
})


function concurrencyRequest(urls, limit, timeout) {
    const total = urls.length;
    return new Promise((resolve, reject) => {

        if (total === 0) {
            resolve([])
        }

        let currentIndex = 0;
        let pi = 0
        let proms = [];
        while (currentIndex < limit) {
            _run(fetch(urls.shift()).then((response) => response.json()), currentIndex++)
        }
        async function _run(task, index) {
            try {
                const res = await Promise.race([
                    task,
                    new Promise((resolve, reject) => {
                        setTimeout(() => {
                            resolve('timeout')
                        }, timeout)
                    })
                ]);
                proms[index] = res
            } catch (error) {
                proms[index] = error
            } finally {
                if (urls.length) {
                    _run(fetch(urls.shift()).then((response) => response.json()), currentIndex++)
                }
                pi++
                if (total === pi) {
                    resolve(proms);
                }
            }
        }
    })
}

